package concurrecy;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

class Car1 {
    private Lock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();

    public void waxed() throws InterruptedException {
        lock.lockInterruptibly();
        try {
            condition.signalAll();
        } finally {
            lock.unlock();
        }
    }

    public void buffed() throws InterruptedException {
        lock.lockInterruptibly();
        try {
            condition.signalAll();
        } finally {
            lock.unlock();
        }
    }

    public void waitingForWax() throws InterruptedException {
        lock.lockInterruptibly();
        try {
            System.out.println("waiting for wax");
            condition.await();
        } finally {
            lock.unlock();
        }
    }

    public void waitingForBuff() throws InterruptedException {
        lock.lockInterruptibly();
        try {
            System.out.println("waiting for buff");
            condition.await();
        } finally {
            lock.unlock();
        }
    }
}

class WaxOn1 implements Runnable {
    private Car1 car;

    public WaxOn1(Car1 car) {
        this.car = car;
    }

    @Override
    public void run() {
        try {
            while (!Thread.interrupted()) {
                TimeUnit.MILLISECONDS.sleep(200);
                car.waxed();
                car.waitingForBuff();
            }
        } catch(InterruptedException e) {
            System.out.println("wax on interrupted");
        }
    }
}

class WaxOff1 implements Runnable {
    private Car1 car;

    public WaxOff1(Car1 car) {
        this.car = car;
    }

    @Override
    public void run() {
        try {
            while(!Thread.interrupted()) {
                car.waitingForWax();
                TimeUnit.MILLISECONDS.sleep(300);
                car.buffed();
            }
        } catch(InterruptedException e) {
            System.out.println("wax off interrupted");
        }
    }
}

/**
 * 使用await sign
 */
public class Wax1Demo {
    public static void main(String[] args) throws InterruptedException {
        Car1 car = new Car1();
        ExecutorService service = Executors.newCachedThreadPool();
        service.execute(new WaxOff1(car));
        service.execute(new WaxOn1(car));

        TimeUnit.SECONDS.sleep(5);
        service.shutdownNow();
    }
}
